#include "proc/cpu.h"
#include "mem/vmem.h"
#include "mem/pmem.h"
#include "mem/mmap.h"
#include "lib/str.h"
#include "lib/print.h"
#include "dev/timer.h"
#include "syscall/sysfunc.h"
#include "syscall/syscall.h"
#include "memlayout.h"
#include "fs/bitmap.h"
#include "fs/buf.h"
#include "fs/fs.h"
#include "proc/elf.h"
#include "fs/dir.h"
#include "fs/inode.h"

extern struct timer sys_timer;

// 堆伸缩
uint64 sys_brk() {
    struct proc *p = myproc();
    uint64 new_heap_top, addr = p->heap_top;

    arg_uint64(0, &new_heap_top);

    // 查询堆顶
    if (new_heap_top == 0) {
        return addr;
    }

    // 扩展堆空间
    if (new_heap_top > addr) {
        uint64 increment = new_heap_top - addr;
        p->heap_top = uvm_heap_grow(p->pgtbl, addr, increment, PTE_R | PTE_W | PTE_U);
        if (p->heap_top != new_heap_top) return -1;
    }
    // 缩小堆空间
    else {
        uint64 decrement = addr - new_heap_top;
        p->heap_top = uvm_heap_ungrow(p->pgtbl, addr, decrement);
    }

    return p->heap_top;
}

// 内存映射
uint64 sys_mmap() {
    uint64 start;
    uint32 len;
    arg_uint64(0, &start);
    arg_uint32(1, &len);

    if (len % PGSIZE != 0) return -1;

    uint32 pages = len / PGSIZE;
    struct proc *p = myproc();

    if (start == 0) {
        mmap_region_t *m = p->mmap;
        while (m && m->npages < pages) {
            m = m->next;
        }
        if (m) {
            uvm_mmap(m->begin, pages, PTE_U | PTE_W | PTE_R);
        } else {
            return -1;
        }
    } else {
        uvm_mmap(start, pages, PTE_U | PTE_W | PTE_R);
    }

    return start;
}

// 取消内存映射
uint64 sys_munmap() {
    uint64 start;
    uint32 len;
    arg_uint64(0, &start);
    arg_uint32(1, &len);

    if (len % PGSIZE != 0) return -1;

    uvm_munmap(start, len / PGSIZE);
    return 0;
}

// 进程复制
uint64 sys_fork() {
    return proc_fork();  // 创建子进程
}

// 进程等待
uint64 sys_wait() {
    uint64 exit_addr;
    arg_uint64(0, &exit_addr);
    return proc_wait(exit_addr);
}

// 进程退出
uint64 sys_exit() {
    uint32 exit_state;
    arg_uint32(0, &exit_state);
    proc_exit(exit_state);
    return exit_state;
}

// 进程睡眠
uint64 sys_sleep() {
    uint32 sleep_duration, start_ticks;
    arg_uint32(0, &sleep_duration);

    spinlock_acquire(&sys_timer.lk);
    start_ticks = sys_timer.ticks;

    while (sys_timer.ticks - start_ticks < sleep_duration * 100) {
        proc_sleep(&sys_timer.ticks, &sys_timer.lk);
    }

    spinlock_release(&sys_timer.lk);
    return 0;
}

// 执行ELF文件
uint64 sys_exec() {
    char path[DIR_PATH_LEN];
    char *argv[ELF_MAXARGS];
    uint64 uargv, uarg;

    arg_str(0, path, DIR_PATH_LEN);
    arg_uint64(1, &uargv);

    memset(argv, 0, sizeof(argv));

    // 复制参数
    for (int i = 0; i < ELF_MAXARGS; i++) {
        uvm_copyin(myproc()->pgtbl, (uint64)&uarg, uargv + sizeof(uint64) * i, sizeof(uint64));
        if (uarg == 0) break;

        argv[i] = (char*)pmem_alloc(false);
        if (argv[i] == NULL) return -1;
        uvm_copyin_str(myproc()->pgtbl, (uint64)argv[i], uarg, PGSIZE);
    }

    int ret = proc_exec(path, argv);

    // 释放内存
    for (int i = 0; i < ELF_MAXARGS && argv[i] != NULL; i++) {
        pmem_free((uint64)argv[i], false);
    }

    return ret;
}



